{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Quantum simulation of electronic structure",
      "provenance": [],
      "collapsed_sections": [
        "Wp1a_Zf8EUen"
      ],
      "include_colab_link": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/JackHidary/quantumcomputingbook/blob/master/Notes/Quantum_simulation_of_electronic_structure.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zeDOA0lc6YyI",
        "colab_type": "code",
        "outputId": "564ccb92-4eba-404a-d135-60974eb41410",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1927
        }
      },
      "source": [
        "!pip install openfermion openfermioncirq pyscf openfermionpyscf"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Collecting openfermion\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/6b/29/0090647a45677f44734c8aab0ec55671416be4ef3c0657c24fb40f5abd14/openfermion-0.9.0.tar.gz (608kB)\n",
            "\u001b[K     |████████████████████████████████| 614kB 4.8MB/s \n",
            "\u001b[?25hCollecting openfermioncirq\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/d5/d0/bca67f760bba1e49796b64d75dcc0c40be426e309fa3e2d691e519cd255b/openfermioncirq-0.3.0-py3-none-any.whl (114kB)\n",
            "\u001b[K     |████████████████████████████████| 122kB 42.9MB/s \n",
            "\u001b[?25hCollecting pyscf\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/50/a9/94b4db1d0ec1089c13db54c2d52c4d8e516e8492cd61d8324731e413feff/pyscf-1.6.1.post1-cp36-cp36m-manylinux1_x86_64.whl (21.4MB)\n",
            "\u001b[K     |████████████████████████████████| 21.4MB 1.7MB/s \n",
            "\u001b[?25hCollecting openfermionpyscf\n",
            "  Downloading https://files.pythonhosted.org/packages/cb/6e/01bc7d2e478ea75b9b5dd262c876f5e7d32105e713b588af5b0121def125/openfermionpyscf-0.4.tar.gz\n",
            "Requirement already satisfied: numpy>=1.11.0 in /usr/local/lib/python3.6/dist-packages (from openfermion) (1.16.3)\n",
            "Requirement already satisfied: scipy>=1.1.0 in /usr/local/lib/python3.6/dist-packages (from openfermion) (1.2.1)\n",
            "Requirement already satisfied: h5py>=2.8 in /usr/local/lib/python3.6/dist-packages (from openfermion) (2.8.0)\n",
            "Requirement already satisfied: future in /usr/local/lib/python3.6/dist-packages (from openfermion) (0.16.0)\n",
            "Requirement already satisfied: jupyter in /usr/local/lib/python3.6/dist-packages (from openfermion) (1.0.0)\n",
            "Requirement already satisfied: nbformat in /usr/local/lib/python3.6/dist-packages (from openfermion) (4.4.0)\n",
            "Requirement already satisfied: networkx in /usr/local/lib/python3.6/dist-packages (from openfermion) (2.3)\n",
            "Requirement already satisfied: matplotlib in /usr/local/lib/python3.6/dist-packages (from openfermion) (3.0.3)\n",
            "Collecting pubchempy (from openfermion)\n",
            "  Downloading https://files.pythonhosted.org/packages/aa/fb/8de3aa9804b614dbc8dc5c16ed061d819cc360e0ddecda3dcd01c1552339/PubChemPy-1.0.4.tar.gz\n",
            "Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from openfermion) (1.12.0)\n",
            "Requirement already satisfied: pandas in /usr/local/lib/python3.6/dist-packages (from openfermioncirq) (0.24.2)\n",
            "Collecting cirq==0.4.0 (from openfermioncirq)\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/99/b7/df9b3297b5ef6e03e31ea86ed7f3532a5b386002365a983536881f9f272c/cirq-0.4.0-py3-none-any.whl (550kB)\n",
            "\u001b[K     |████████████████████████████████| 552kB 37.2MB/s \n",
            "\u001b[?25hRequirement already satisfied: pytest in /usr/local/lib/python3.6/dist-packages (from openfermionpyscf) (3.6.4)\n",
            "Requirement already satisfied: qtconsole in /usr/local/lib/python3.6/dist-packages (from jupyter->openfermion) (4.4.4)\n",
            "Requirement already satisfied: ipywidgets in /usr/local/lib/python3.6/dist-packages (from jupyter->openfermion) (7.4.2)\n",
            "Requirement already satisfied: ipykernel in /usr/local/lib/python3.6/dist-packages (from jupyter->openfermion) (4.6.1)\n",
            "Requirement already satisfied: notebook in /usr/local/lib/python3.6/dist-packages (from jupyter->openfermion) (5.2.2)\n",
            "Requirement already satisfied: nbconvert in /usr/local/lib/python3.6/dist-packages (from jupyter->openfermion) (5.5.0)\n",
            "Requirement already satisfied: jupyter-console in /usr/local/lib/python3.6/dist-packages (from jupyter->openfermion) (6.0.0)\n",
            "Requirement already satisfied: traitlets>=4.1 in /usr/local/lib/python3.6/dist-packages (from nbformat->openfermion) (4.3.2)\n",
            "Requirement already satisfied: jupyter-core in /usr/local/lib/python3.6/dist-packages (from nbformat->openfermion) (4.4.0)\n",
            "Requirement already satisfied: jsonschema!=2.5.0,>=2.4 in /usr/local/lib/python3.6/dist-packages (from nbformat->openfermion) (2.6.0)\n",
            "Requirement already satisfied: ipython-genutils in /usr/local/lib/python3.6/dist-packages (from nbformat->openfermion) (0.2.0)\n",
            "Requirement already satisfied: decorator>=4.3.0 in /usr/local/lib/python3.6/dist-packages (from networkx->openfermion) (4.4.0)\n",
            "Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->openfermion) (2.5.3)\n",
            "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->openfermion) (1.1.0)\n",
            "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib->openfermion) (0.10.0)\n",
            "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->openfermion) (2.4.0)\n",
            "Requirement already satisfied: pytz>=2011k in /usr/local/lib/python3.6/dist-packages (from pandas->openfermioncirq) (2018.9)\n",
            "Collecting typing-extensions (from cirq==0.4.0->openfermioncirq)\n",
            "  Downloading https://files.pythonhosted.org/packages/0f/62/c66e553258c37c33f9939abb2dd8d2481803d860ff68e635466f12aa7efa/typing_extensions-3.7.2-py3-none-any.whl\n",
            "Requirement already satisfied: protobuf~=3.5 in /usr/local/lib/python3.6/dist-packages (from cirq==0.4.0->openfermioncirq) (3.7.1)\n",
            "Requirement already satisfied: google-api-python-client~=1.6 in /usr/local/lib/python3.6/dist-packages (from cirq==0.4.0->openfermioncirq) (1.6.7)\n",
            "Requirement already satisfied: requests~=2.18 in /usr/local/lib/python3.6/dist-packages (from cirq==0.4.0->openfermioncirq) (2.21.0)\n",
            "Requirement already satisfied: sortedcontainers~=2.0 in /usr/local/lib/python3.6/dist-packages (from cirq==0.4.0->openfermioncirq) (2.1.0)\n",
            "Requirement already satisfied: more-itertools>=4.0.0 in /usr/local/lib/python3.6/dist-packages (from pytest->openfermionpyscf) (7.0.0)\n",
            "Requirement already satisfied: pluggy<0.8,>=0.5 in /usr/local/lib/python3.6/dist-packages (from pytest->openfermionpyscf) (0.7.1)\n",
            "Requirement already satisfied: atomicwrites>=1.0 in /usr/local/lib/python3.6/dist-packages (from pytest->openfermionpyscf) (1.3.0)\n",
            "Requirement already satisfied: attrs>=17.4.0 in /usr/local/lib/python3.6/dist-packages (from pytest->openfermionpyscf) (19.1.0)\n",
            "Requirement already satisfied: py>=1.5.0 in /usr/local/lib/python3.6/dist-packages (from pytest->openfermionpyscf) (1.8.0)\n",
            "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from pytest->openfermionpyscf) (41.0.1)\n",
            "Requirement already satisfied: jupyter-client>=4.1 in /usr/local/lib/python3.6/dist-packages (from qtconsole->jupyter->openfermion) (5.2.4)\n",
            "Requirement already satisfied: pygments in /usr/local/lib/python3.6/dist-packages (from qtconsole->jupyter->openfermion) (2.1.3)\n",
            "Requirement already satisfied: ipython>=4.0.0; python_version >= \"3.3\" in /usr/local/lib/python3.6/dist-packages (from ipywidgets->jupyter->openfermion) (5.5.0)\n",
            "Requirement already satisfied: widgetsnbextension~=3.4.0 in /usr/local/lib/python3.6/dist-packages (from ipywidgets->jupyter->openfermion) (3.4.2)\n",
            "Requirement already satisfied: tornado>=4.0 in /usr/local/lib/python3.6/dist-packages (from ipykernel->jupyter->openfermion) (4.5.3)\n",
            "Requirement already satisfied: jinja2 in /usr/local/lib/python3.6/dist-packages (from notebook->jupyter->openfermion) (2.10.1)\n",
            "Requirement already satisfied: terminado>=0.3.3; sys_platform != \"win32\" in /usr/local/lib/python3.6/dist-packages (from notebook->jupyter->openfermion) (0.8.2)\n",
            "Requirement already satisfied: entrypoints>=0.2.2 in /usr/local/lib/python3.6/dist-packages (from nbconvert->jupyter->openfermion) (0.3)\n",
            "Requirement already satisfied: mistune>=0.8.1 in /usr/local/lib/python3.6/dist-packages (from nbconvert->jupyter->openfermion) (0.8.4)\n",
            "Requirement already satisfied: bleach in /usr/local/lib/python3.6/dist-packages (from nbconvert->jupyter->openfermion) (3.1.0)\n",
            "Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.6/dist-packages (from nbconvert->jupyter->openfermion) (1.4.2)\n",
            "Requirement already satisfied: testpath in /usr/local/lib/python3.6/dist-packages (from nbconvert->jupyter->openfermion) (0.4.2)\n",
            "Requirement already satisfied: defusedxml in /usr/local/lib/python3.6/dist-packages (from nbconvert->jupyter->openfermion) (0.6.0)\n",
            "Collecting prompt-toolkit<2.1.0,>=2.0.0 (from jupyter-console->jupyter->openfermion)\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/f7/a7/9b1dd14ef45345f186ef69d175bdd2491c40ab1dfa4b2b3e4352df719ed7/prompt_toolkit-2.0.9-py3-none-any.whl (337kB)\n",
            "\u001b[K     |████████████████████████████████| 337kB 37.1MB/s \n",
            "\u001b[?25hRequirement already satisfied: uritemplate<4dev,>=3.0.0 in /usr/local/lib/python3.6/dist-packages (from google-api-python-client~=1.6->cirq==0.4.0->openfermioncirq) (3.0.0)\n",
            "Requirement already satisfied: httplib2<1dev,>=0.9.2 in /usr/local/lib/python3.6/dist-packages (from google-api-python-client~=1.6->cirq==0.4.0->openfermioncirq) (0.11.3)\n",
            "Requirement already satisfied: oauth2client<5.0.0dev,>=1.5.0 in /usr/local/lib/python3.6/dist-packages (from google-api-python-client~=1.6->cirq==0.4.0->openfermioncirq) (4.1.3)\n",
            "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests~=2.18->cirq==0.4.0->openfermioncirq) (2019.3.9)\n",
            "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests~=2.18->cirq==0.4.0->openfermioncirq) (1.24.3)\n",
            "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests~=2.18->cirq==0.4.0->openfermioncirq) (3.0.4)\n",
            "Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests~=2.18->cirq==0.4.0->openfermioncirq) (2.8)\n",
            "Requirement already satisfied: pyzmq>=13 in /usr/local/lib/python3.6/dist-packages (from jupyter-client>=4.1->qtconsole->jupyter->openfermion) (17.0.0)\n",
            "Requirement already satisfied: simplegeneric>0.8 in /usr/local/lib/python3.6/dist-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets->jupyter->openfermion) (0.8.1)\n",
            "Requirement already satisfied: pexpect; sys_platform != \"win32\" in /usr/local/lib/python3.6/dist-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets->jupyter->openfermion) (4.7.0)\n",
            "Requirement already satisfied: pickleshare in /usr/local/lib/python3.6/dist-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets->jupyter->openfermion) (0.7.5)\n",
            "Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.6/dist-packages (from jinja2->notebook->jupyter->openfermion) (1.1.1)\n",
            "Requirement already satisfied: ptyprocess; os_name != \"nt\" in /usr/local/lib/python3.6/dist-packages (from terminado>=0.3.3; sys_platform != \"win32\"->notebook->jupyter->openfermion) (0.6.0)\n",
            "Requirement already satisfied: webencodings in /usr/local/lib/python3.6/dist-packages (from bleach->nbconvert->jupyter->openfermion) (0.5.1)\n",
            "Requirement already satisfied: wcwidth in /usr/local/lib/python3.6/dist-packages (from prompt-toolkit<2.1.0,>=2.0.0->jupyter-console->jupyter->openfermion) (0.1.7)\n",
            "Requirement already satisfied: pyasn1>=0.1.7 in /usr/local/lib/python3.6/dist-packages (from oauth2client<5.0.0dev,>=1.5.0->google-api-python-client~=1.6->cirq==0.4.0->openfermioncirq) (0.4.5)\n",
            "Requirement already satisfied: pyasn1-modules>=0.0.5 in /usr/local/lib/python3.6/dist-packages (from oauth2client<5.0.0dev,>=1.5.0->google-api-python-client~=1.6->cirq==0.4.0->openfermioncirq) (0.2.5)\n",
            "Requirement already satisfied: rsa>=3.1.4 in /usr/local/lib/python3.6/dist-packages (from oauth2client<5.0.0dev,>=1.5.0->google-api-python-client~=1.6->cirq==0.4.0->openfermioncirq) (4.0)\n",
            "Building wheels for collected packages: openfermion, openfermionpyscf, pubchempy\n",
            "  Building wheel for openfermion (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Stored in directory: /root/.cache/pip/wheels/c6/24/16/1ee82a50a11993a78c73f1fe208cd83c5c69d0930c1ca1817b\n",
            "  Building wheel for openfermionpyscf (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Stored in directory: /root/.cache/pip/wheels/3e/f9/5d/a25b8657561bca070de8ab1d3a01f4027a9e0413a364fbd767\n",
            "  Building wheel for pubchempy (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Stored in directory: /root/.cache/pip/wheels/10/4d/51/6b843681a9a5aef35f0d0fbce243de46f85080036e16118752\n",
            "Successfully built openfermion openfermionpyscf pubchempy\n",
            "\u001b[31mERROR: ipython 5.5.0 has requirement prompt-toolkit<2.0.0,>=1.0.4, but you'll have prompt-toolkit 2.0.9 which is incompatible.\u001b[0m\n",
            "\u001b[31mERROR: cirq 0.4.0 has requirement matplotlib~=2.2, but you'll have matplotlib 3.0.3 which is incompatible.\u001b[0m\n",
            "Installing collected packages: pubchempy, openfermion, typing-extensions, cirq, openfermioncirq, pyscf, openfermionpyscf, prompt-toolkit\n",
            "  Found existing installation: prompt-toolkit 1.0.16\n",
            "    Uninstalling prompt-toolkit-1.0.16:\n",
            "      Successfully uninstalled prompt-toolkit-1.0.16\n",
            "Successfully installed cirq-0.4.0 openfermion-0.9.0 openfermioncirq-0.3.0 openfermionpyscf-0.4 prompt-toolkit-2.0.9 pubchempy-1.0.4 pyscf-1.6.1.post1 typing-extensions-3.7.2\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.colab-display-data+json": {
              "pip_warning": {
                "packages": [
                  "prompt_toolkit"
                ]
              }
            }
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GzfsOoPI5sHP",
        "colab_type": "text"
      },
      "source": [
        "# Quantum simulation of electronic structure\n",
        "\n",
        "The quantum simulation of electronic structure is one of the most promising applications of quantum computers. It has potential applications to materials and drug design. This tutorial provides an introduction to OpenFermion, a library for obtaining and manipulating representations of fermionic and qubit Hamiltonians, and OpenFermion-Cirq, a companion library used to to compile quantum simulation circuits in Cirq.\n",
        "\n",
        "## Background\n",
        "\n",
        "A system of $N$ fermionic modes is\n",
        "described by a set of fermionic *annihilation operators*\n",
        "$\\{a_p\\}_{p=0}^{N-1}$ satisfying the *canonical anticommutation relations*\n",
        "$$\\begin{aligned}\n",
        "    \\{a_p, a_q\\} &= 0, \\\\\n",
        "    \\{a_p, a^\\dagger_q\\} &= \\delta_{pq},\n",
        "  \\end{aligned}$$ where $\\{A, B\\} := AB + BA$. The adjoint\n",
        "$a^\\dagger_p$ of an annihilation operator $a_p$ is called a *creation\n",
        "operator*, and we refer to creation and annihilation operators as\n",
        "fermionic *ladder operators*.\n",
        "    \n",
        "The canonical anticommutation relations impose a number of consequences on the structure of the vector space on which the ladder operators act; see [Michael Nielsen's notes](http://michaelnielsen.org/blog/archive/notes/fermions_and_jordan_wigner.pdf) for a good discussion.\n",
        "\n",
        "The electronic structure Hamiltonian is commonly written in the form\n",
        "$$\n",
        "\\sum_{pq} T_{pq} a_p^\\dagger a_q + \\sum_{pqrs} V_{pqrs} a_p^\\dagger a_q^\\dagger a_r a_s\n",
        "$$\n",
        "where the $T_{pq}$ and $V_{pqrs}$ are coefficients which depend on the physical system being described. We are interested in calculating the lowest eigenvalue of the Hamiltonian. This eigenvalue is also called the ground state energy.\n",
        "\n",
        "\n",
        "## FermionOperator and QubitOperator\n",
        "\n",
        "### FermionOperator\n",
        "\n",
        "- Stores a weighted sum (linear combination) of fermionic terms\n",
        "- A fermionic term is a product of ladder operators\n",
        "- Examples of things that can be represented by FermionOperator:\n",
        "$$\n",
        "\\begin{align}\n",
        "& a_1 \\nonumber \\\\\n",
        "& 1.7 a^\\dagger_3 \\nonumber \\\\\n",
        "&-1.7 \\, a^\\dagger_3 a_1 \\nonumber \\\\\n",
        "&(1 + 2i) \\, a^\\dagger_4 a^\\dagger_3 a_9 a_1 \\nonumber \\\\\n",
        "&(1 + 2i) \\, a^\\dagger_4 a^\\dagger_3 a_9 a_1 - 1.7 \\, a^\\dagger_3 a_1 \\nonumber\n",
        "\\end{align}\n",
        "$$\n",
        "\n",
        "- A fermionic term is internally represented as a tuple of tuples\n",
        "- Each inner tuple represents a single ladder operator as (index, action)\n",
        "- Examples of fermionic terms:\n",
        "$$\n",
        "\\begin{align}\n",
        "I & \\mapsto () \\nonumber \\\\\n",
        "a_1 & \\mapsto ((1, 0),) \\nonumber \\\\\n",
        "a^\\dagger_3 & \\mapsto ((3, 1),) \\nonumber \\\\\n",
        "a^\\dagger_3 a_1 & \\mapsto ((3, 1), (1, 0)) \\nonumber \\\\\n",
        "a^\\dagger_4 a^\\dagger_3 a_9 a_1 & \\mapsto ((4, 1), (3, 1), (9, 0), (1, 0)) \\nonumber\n",
        "\\end{align}\n",
        "$$\n",
        "\n",
        "- FermionOperator is a sum of terms, represented as a dictionary from term to coefficient"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "u1J3mO4r5sHR",
        "colab_type": "code",
        "outputId": "1ba8429f-e874-421d-85c4-ce5a46890d8b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "import openfermion as of\n",
        "\n",
        "op = of.FermionOperator(((4, 1), (3, 1), (9, 0), (1, 0)), 1+2j) + of.FermionOperator(((3, 1), (1, 0)), -1.7)\n",
        "\n",
        "print(op.terms)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{((4, 1), (3, 1), (9, 0), (1, 0)): (1+2j), ((3, 1), (1, 0)): -1.7}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6gMYqNFi5sHV",
        "colab_type": "text"
      },
      "source": [
        "Alternative notation, useful when playing around:\n",
        "\n",
        "$$\n",
        "\\begin{align}\n",
        "I & \\mapsto \\textrm{\"\"} \\nonumber \\\\\n",
        "a_1 & \\mapsto \\textrm{\"1\"} \\nonumber \\\\\n",
        "a^\\dagger_3 & \\mapsto \\textrm{\"3^\"} \\nonumber \\\\\n",
        "a^\\dagger_3 a_1 & \\mapsto \\textrm{\"3^}\\;\\textrm{1\"} \\nonumber \\\\\n",
        "a^\\dagger_4 a^\\dagger_3 a_9 a_1 & \\mapsto \\textrm{\"4^}\\;\\textrm{3^}\\;\\textrm{9}\\;\\textrm{1\"} \\nonumber\n",
        "\\end{align}\n",
        "$$"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "w55QckU25sHW",
        "colab_type": "code",
        "outputId": "c5b1144d-cbb2-426f-db97-df59fda24bdd",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "op = of.FermionOperator('4^ 3^ 9 1', 1+2j) + of.FermionOperator('3^ 1', -1.7)\n",
        "\n",
        "print(op.terms)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{((4, 1), (3, 1), (9, 0), (1, 0)): (1+2j), ((3, 1), (1, 0)): -1.7}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hRrwfjR55sHZ",
        "colab_type": "text"
      },
      "source": [
        "Just print the operator for a nice readable representation:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "VYnPilSU5sHa",
        "colab_type": "code",
        "outputId": "303af9dc-9106-4268-c4a2-e9f9554e8bd8",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 51
        }
      },
      "source": [
        "print(op)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "-1.7 [3^ 1] +\n",
            "(1+2j) [4^ 3^ 9 1]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vvZxYedI5sHw",
        "colab_type": "text"
      },
      "source": [
        "### QubitOperator\n",
        "\n",
        "Same as FermionOperator, but the possible actions are 'X', 'Y', and 'Z' instead of 1 and 0."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "79UFeqFz5sHw",
        "colab_type": "code",
        "outputId": "fabd096a-dfc0-4b6e-fd40-23a8da479e68",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 51
        }
      },
      "source": [
        "op = of.QubitOperator(((1, 'X'), (2, 'Y'), (3, 'Z')))\n",
        "op += of.QubitOperator('X3 Z4', 3.0)\n",
        "\n",
        "print(op)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1.0 [X1 Y2 Z3] +\n",
            "3.0 [X3 Z4]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "v_PQSbeB5sH1",
        "colab_type": "text"
      },
      "source": [
        "FermionOperator and QubitOperator actually inherit from the same parent class, SymbolicOperator."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "AE28NBCu5sH5",
        "colab_type": "text"
      },
      "source": [
        "## The Jordan-Wigner and Bravyi-Kitaev transforms\n",
        "\n",
        "A fermionic transform maps FermionOperators to QubitOperators in a way that preserves the canonical anticommutation relations. The most basic transforms are the Jordan-Wigner transform (JWT) and Bravyi-Kitaev transform (BKT). Note that the BKT requires the total number of qubits to be predetermined. Whenever a fermionic transform is being applied implicitly, it is the JWT."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Cum2qpwA5sH6",
        "colab_type": "code",
        "outputId": "44882491-8adf-4481-a67a-a1cd6200b5a6",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 170
        }
      },
      "source": [
        "op = of.FermionOperator('2^ 15')\n",
        "\n",
        "print(of.jordan_wigner(op))\n",
        "print()\n",
        "print(of.bravyi_kitaev(op, n_qubits=16))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "(0.25+0j) [X2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z10 Z11 Z12 Z13 Z14 X15] +\n",
            "0.25j [X2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z10 Z11 Z12 Z13 Z14 Y15] +\n",
            "-0.25j [Y2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z10 Z11 Z12 Z13 Z14 X15] +\n",
            "(0.25+0j) [Y2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z10 Z11 Z12 Z13 Z14 Y15]\n",
            "\n",
            "(-0.25+0j) [Z1 X2 X3 X7 Z15] +\n",
            "-0.25j [Z1 X2 X3 Y7 Z11 Z13 Z14] +\n",
            "0.25j [Z1 Y2 X3 X7 Z15] +\n",
            "(-0.25+0j) [Z1 Y2 X3 Y7 Z11 Z13 Z14]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9T6yt_Nu5sH_",
        "colab_type": "text"
      },
      "source": [
        "\n",
        "### Exercise\n",
        "\n",
        "Below are some examples of how FermionOperators are mapped to QubitOperators by the Jordan-Wigner transform (the notation 'h.c.' stands for 'hermitian conjugate'):\n",
        "$$\n",
        "\\begin{align*}\n",
        "    a_p^\\dagger &\\mapsto \\frac12 (X_p - i Y_p) Z_0 \\cdots Z_{p-1}\\\\\n",
        "    a_p^\\dagger a_p &\\mapsto \\frac12 (I - Z_p)\\\\\n",
        "    (\\beta a_p^\\dagger a_q + \\text{h.c.}) &\\mapsto \\frac12 [\\text{Re}(\\beta) (X_p ZZ \\cdots ZZ X_q + Y_p ZZ \\cdots ZZ Y_q) + \\text{Im}(\\beta) (Y_p ZZ \\cdots ZZ X_q - X_p ZZ \\cdots ZZ Y_q)]\n",
        "\\end{align*}\n",
        "$$\n",
        "Verify these mappings for $p=2$ and $q=7$. The `hermitian_conjugated` function may be useful here."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "o1bOGrkvUHVq",
        "colab_type": "code",
        "outputId": "9c732d30-9934-4fa8-b57c-a9610df24d6b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 191
        }
      },
      "source": [
        "a2 = of.FermionOperator('2')\n",
        "print(of.jordan_wigner(a2))\n",
        "print()\n",
        "\n",
        "a2dag = of.FermionOperator('2^')\n",
        "print(of.jordan_wigner(a2dag*a2))\n",
        "print()\n",
        "\n",
        "a7 = of.FermionOperator('7')\n",
        "a7dag = of.FermionOperator('7^')\n",
        "print(of.jordan_wigner((1+2j)*(a2dag*a7) + (1-2j)*(a7dag*a2)))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0.5 [Z0 Z1 X2] +\n",
            "0.5j [Z0 Z1 Y2]\n",
            "\n",
            "(0.5+0j) [] +\n",
            "(-0.5+0j) [Z2]\n",
            "\n",
            "(0.5+0j) [X2 Z3 Z4 Z5 Z6 X7] +\n",
            "(-1+0j) [X2 Z3 Z4 Z5 Z6 Y7] +\n",
            "(1+0j) [Y2 Z3 Z4 Z5 Z6 X7] +\n",
            "(0.5+0j) [Y2 Z3 Z4 Z5 Z6 Y7]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gSwBGl9UUy1k",
        "colab_type": "text"
      },
      "source": [
        "### Solution"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "xwDvR6Ol5sIA",
        "colab_type": "code",
        "outputId": "589d78d2-5e04-425a-92f9-3e48f71a21c5",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 187
        }
      },
      "source": [
        "a2 = of.FermionOperator('2')\n",
        "a2dag = of.FermionOperator('2^')\n",
        "a7 = of.FermionOperator('7')\n",
        "a7dag = of.FermionOperator('7^')\n",
        "\n",
        "\n",
        "print(of.jordan_wigner(a2dag))\n",
        "print()\n",
        "print(of.jordan_wigner(a2dag*a2))\n",
        "print()\n",
        "\n",
        "op = (2+3j)*a2dag*a7\n",
        "op += of.hermitian_conjugated(op)\n",
        "print(of.jordan_wigner(op))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0.5 [Z0 Z1 X2] +\n",
            "-0.5j [Z0 Z1 Y2]\n",
            "\n",
            "(0.5+0j) [] +\n",
            "(-0.5+0j) [Z2]\n",
            "\n",
            "(1+0j) [X2 Z3 Z4 Z5 Z6 X7] +\n",
            "(-1.5+0j) [X2 Z3 Z4 Z5 Z6 Y7] +\n",
            "(1.5+0j) [Y2 Z3 Z4 Z5 Z6 X7] +\n",
            "(1+0j) [Y2 Z3 Z4 Z5 Z6 Y7]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "j2BmxWOu5sIC",
        "colab_type": "text"
      },
      "source": [
        "### Exercise\n",
        "Use the `+` and `*` operators to verify that after applying the JWT to ladder operators, the resulting QubitOperators satisfy\n",
        "$$\n",
        "\\begin{align}\n",
        "    a_2 a_7 + a_7 a_2 &= 0 \\\\\n",
        "    a_2 a_7^\\dagger + a_7^\\dagger a_2 &= 0\\\\\n",
        "    a_2 a_2^\\dagger + a_2^\\dagger a_2 &= 1\n",
        "\\end{align}\n",
        "$$"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VsJlMb_GVU1Y",
        "colab_type": "text"
      },
      "source": [
        "### Solution"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "yzwsrS1O5sID",
        "colab_type": "code",
        "outputId": "7be659e8-1c0e-48c3-f8a7-1560bebb90b2",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 68
        }
      },
      "source": [
        "a2_jw = of.jordan_wigner(a2)\n",
        "a2dag_jw = of.jordan_wigner(a2dag)\n",
        "a7_jw = of.jordan_wigner(a7)\n",
        "a7dag_jw = of.jordan_wigner(a7dag)\n",
        "\n",
        "print(a2_jw * a7_jw + a7_jw * a2_jw)\n",
        "print(a2_jw * a7dag_jw + a7dag_jw * a2_jw)\n",
        "print(a2_jw * a2dag_jw + a2dag_jw * a2_jw)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0\n",
            "0\n",
            "(1+0j) []\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "p1fQ3-DK5sIS",
        "colab_type": "text"
      },
      "source": [
        "## Array data structures\n",
        "\n",
        "- When FermionOperators have specialized structure we can store coefficients in numpy arrays, enabling fast numerical manipulation.\n",
        "- Array data structures can always be converted to FermionOperator using `get_fermion_operator`.\n",
        "\n",
        "### InteractionOperator\n",
        "\n",
        "- Stores the one- and two-body tensors $T_{pq}$ and $V_{pqrs}$ of the molecular Hamiltonian\n",
        "$$\n",
        "\\sum_{pq} T_{pq} a_p^\\dagger a_q + \\sum_{pqrs} V_{pqrs} a_p^\\dagger a_q^\\dagger a_r a_s\n",
        "$$\n",
        "- Default data structure for molecular Hamiltonians\n",
        "- Convert from FermionOperator using `get_interaction_operator`\n",
        "\n",
        "### DiagonalCoulombHamiltonian\n",
        "\n",
        "- Stores the one- and two-body coefficient matrices $T_{pq}$ and $V_{pq}$ of a Hamiltonian with a diagonal Coulomb term:\n",
        "$$\n",
        "\\sum_{pq} T_{pq} a_p^\\dagger a_q + \\sum_{pq} V_{pq} a_p^\\dagger a_p a_q^\\dagger a_q\n",
        "$$\n",
        "- Leads to especially efficient algorithms for quantum simulation\n",
        "- Convert from FermionOperator using `get_diagonal_coulomb_hamiltonian`\n",
        "\n",
        "### QuadraticHamiltonian\n",
        "\n",
        "- Stores the Hermitian matrix $M_{pq}$ and antisymmetric matrix $\\Delta_{pq}$ describing a general quadratic Hamiltonian\n",
        "$$\n",
        "\\sum_{p, q} M_{pq} a^\\dagger_p a_q\n",
        "+ \\frac12 \\sum_{p, q}\n",
        "    (\\Delta_{pq} a^\\dagger_p a^\\dagger_q + \\text{h.c.})\n",
        "$$\n",
        "- Routines included for efficient diagonalization (can handle thousands of fermionic modes)\n",
        "- Convert from FermionOperator using `get_quadratic_hamiltonian`"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fN6Bq0gbdK5G",
        "colab_type": "text"
      },
      "source": [
        "## Generating the Hamiltonian for a molecule"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "l_UXxxqw5sIW",
        "colab_type": "text"
      },
      "source": [
        "The cell below demonstrates using one of our electronic structure package plugins, OpenFermion-PySCF, to generate a molecular Hamiltonian for a hydrogen molecule. Note that the Hamiltonian is returned as an InteractionOperator. We'll convert it to a FermionOperator and print the result."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "r8mmL0aj5sIW",
        "colab_type": "code",
        "outputId": "122d86c7-4480-42b4-b72d-a78d9f6d4b9c",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 659
        }
      },
      "source": [
        "import openfermionpyscf as ofpyscf\n",
        "\n",
        "# Set molecule parameters\n",
        "geometry = [('H', (0.0, 0.0, 0.0)), ('H', (0.0, 0.0, 0.8))]\n",
        "basis = 'sto-3g'\n",
        "multiplicity = 1\n",
        "charge = 0\n",
        "\n",
        "# Perform electronic structure calculations and\n",
        "# obtain Hamiltonian as an InteractionOperator\n",
        "hamiltonian = ofpyscf.generate_molecular_hamiltonian(\n",
        "  geometry, basis, multiplicity, charge)\n",
        "\n",
        "# Convert to a FermionOperator\n",
        "hamiltonian_ferm_op = of.get_fermion_operator(hamiltonian)\n",
        "\n",
        "print(hamiltonian_ferm_op)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0.66147151365 [] +\n",
            "-1.2178260299951058 [0^ 0] +\n",
            "0.3316650744318082 [0^ 0^ 0 0] +\n",
            "0.09231339177803066 [0^ 0^ 2 2] +\n",
            "0.3316650744318082 [0^ 1^ 1 0] +\n",
            "0.09231339177803066 [0^ 1^ 3 2] +\n",
            "0.09231339177803066 [0^ 2^ 0 2] +\n",
            "0.3267206861819477 [0^ 2^ 2 0] +\n",
            "0.09231339177803066 [0^ 3^ 1 2] +\n",
            "0.3267206861819477 [0^ 3^ 3 0] +\n",
            "0.3316650744318082 [1^ 0^ 0 1] +\n",
            "0.09231339177803066 [1^ 0^ 2 3] +\n",
            "-1.2178260299951058 [1^ 1] +\n",
            "0.3316650744318082 [1^ 1^ 1 1] +\n",
            "0.09231339177803066 [1^ 1^ 3 3] +\n",
            "0.09231339177803066 [1^ 2^ 0 3] +\n",
            "0.3267206861819477 [1^ 2^ 2 1] +\n",
            "0.09231339177803066 [1^ 3^ 1 3] +\n",
            "0.3267206861819477 [1^ 3^ 3 1] +\n",
            "0.32672068618194783 [2^ 0^ 0 2] +\n",
            "0.09231339177803066 [2^ 0^ 2 0] +\n",
            "0.32672068618194783 [2^ 1^ 1 2] +\n",
            "0.09231339177803066 [2^ 1^ 3 0] +\n",
            "-0.5096378744364826 [2^ 2] +\n",
            "0.09231339177803066 [2^ 2^ 0 0] +\n",
            "0.34339576784573445 [2^ 2^ 2 2] +\n",
            "0.09231339177803066 [2^ 3^ 1 0] +\n",
            "0.34339576784573445 [2^ 3^ 3 2] +\n",
            "0.32672068618194783 [3^ 0^ 0 3] +\n",
            "0.09231339177803066 [3^ 0^ 2 1] +\n",
            "0.32672068618194783 [3^ 1^ 1 3] +\n",
            "0.09231339177803066 [3^ 1^ 3 1] +\n",
            "0.09231339177803066 [3^ 2^ 0 1] +\n",
            "0.34339576784573445 [3^ 2^ 2 3] +\n",
            "-0.5096378744364826 [3^ 3] +\n",
            "0.09231339177803066 [3^ 3^ 1 1] +\n",
            "0.34339576784573445 [3^ 3^ 3 3]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jWxU4bG1oYfZ",
        "colab_type": "text"
      },
      "source": [
        "Let's calculate the ground energy (lowest eigenvalue) of the Hamiltonian. First, we'll map the FermionOperator to a QubitOperator using the JWT. Then, we'll convert the QubitOperator to a Scipy sparse matrix and get its lowest eigenvalue."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "outputId": "6bed94fe-5348-4644-dd5a-8a289ca02a38",
        "id": "rIEH_5eLaxvG",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 312
        }
      },
      "source": [
        "import scipy.sparse\n",
        "\n",
        "# Map to QubitOperator using the JWT\n",
        "hamiltonian_jw = of.jordan_wigner(hamiltonian_ferm_op)\n",
        "\n",
        "# Convert to Scipy sparse matrix\n",
        "hamiltonian_jw_sparse = of.get_sparse_operator(hamiltonian_jw)\n",
        "\n",
        "# Compute ground energy\n",
        "eigs, _ = scipy.sparse.linalg.eigsh(hamiltonian_jw_sparse, k=1, which='SA')\n",
        "ground_energy = eigs[0]\n",
        "\n",
        "print('Ground_energy: {}'.format(ground_energy))\n",
        "print('JWT transformed Hamiltonian:')\n",
        "print(hamiltonian_jw)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Ground_energy: -1.134147666677095\n",
            "JWT transformed Hamiltonian:\n",
            "(-0.16733398905695201+0j) [] +\n",
            "(-0.04615669588901533+0j) [X0 X1 Y2 Y3] +\n",
            "(0.04615669588901533+0j) [X0 Y1 Y2 X3] +\n",
            "(0.04615669588901533+0j) [Y0 X1 X2 Y3] +\n",
            "(-0.04615669588901533+0j) [Y0 Y1 X2 X3] +\n",
            "(0.16251648748871642+0j) [Z0] +\n",
            "(0.1658325372159041+0j) [Z0 Z1] +\n",
            "(0.11720364720195856+0j) [Z0 Z2] +\n",
            "(0.1633603430909739+0j) [Z0 Z3] +\n",
            "(0.16251648748871636+0j) [Z1] +\n",
            "(0.1633603430909739+0j) [Z1 Z2] +\n",
            "(0.11720364720195856+0j) [Z1 Z3] +\n",
            "(-0.1974429369975584+0j) [Z2] +\n",
            "(0.17169788392286722+0j) [Z2 Z3] +\n",
            "(-0.19744293699755838+0j) [Z3]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "gjUBgFx-axmm"
      },
      "source": [
        "### Exercise\n",
        "Compute the ground energy of the same Hamiltonian, but via the Bravyi-Kitaev transform. Verify that you get the same value."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ID2vls21XKj-",
        "colab_type": "code",
        "outputId": "7ac9e638-19fb-4e34-d136-85e73d369091",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 312
        }
      },
      "source": [
        "import scipy.sparse\n",
        "\n",
        "# Map to QubitOperator using the JWT\n",
        "hamiltonian_bk = of.bravyi_kitaev(hamiltonian_ferm_op)\n",
        "\n",
        "# Convert to Scipy sparse matrix\n",
        "hamiltonian_bk_sparse = of.get_sparse_operator(hamiltonian_bk)\n",
        "\n",
        "# Compute ground energy\n",
        "eigs, _ = scipy.sparse.linalg.eigsh(hamiltonian_bk_sparse, k=1, which='SA')\n",
        "ground_energy = eigs[0]\n",
        "\n",
        "print('Ground_energy: {}'.format(ground_energy))\n",
        "print('BK transformed Hamiltonian:')\n",
        "print(hamiltonian_bk)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Ground_energy: -1.1341476666770918\n",
            "BK transformed Hamiltonian:\n",
            "(-0.16733398905695201+0j) [] +\n",
            "(0.04615669588901533+0j) [X0 Z1 X2] +\n",
            "(0.04615669588901533+0j) [X0 Z1 X2 Z3] +\n",
            "(0.04615669588901533+0j) [Y0 Z1 Y2] +\n",
            "(0.04615669588901533+0j) [Y0 Z1 Y2 Z3] +\n",
            "(0.16251648748871642+0j) [Z0] +\n",
            "(0.16251648748871636+0j) [Z0 Z1] +\n",
            "(0.1633603430909739+0j) [Z0 Z1 Z2] +\n",
            "(0.1633603430909739+0j) [Z0 Z1 Z2 Z3] +\n",
            "(0.11720364720195856+0j) [Z0 Z2] +\n",
            "(0.11720364720195856+0j) [Z0 Z2 Z3] +\n",
            "(0.1658325372159041+0j) [Z1] +\n",
            "(-0.19744293699755838+0j) [Z1 Z2 Z3] +\n",
            "(0.17169788392286722+0j) [Z1 Z3] +\n",
            "(-0.1974429369975584+0j) [Z2]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dEqS3XV0eXx1",
        "colab_type": "text"
      },
      "source": [
        "### Solution"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9Ss_OhXo5sIP",
        "colab_type": "code",
        "outputId": "610dcb45-c984-47c7-8f21-d403a0722b1e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 306
        }
      },
      "source": [
        "# Map to QubitOperator using the BKT\n",
        "hamiltonian_bk = of.bravyi_kitaev(hamiltonian_ferm_op)\n",
        "\n",
        "# Convert to Scipy sparse matrix\n",
        "hamiltonian_bk_sparse = of.get_sparse_operator(hamiltonian_bk)\n",
        "\n",
        "# Compute ground state energy\n",
        "eigs, _ = scipy.sparse.linalg.eigsh(hamiltonian_bk_sparse, k=1, which='SA')\n",
        "ground_energy = eigs[0]\n",
        "\n",
        "print('Ground_energy: {}'.format(ground_energy))\n",
        "print('BKT transformed Hamiltonian:')\n",
        "print(hamiltonian_bk)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Ground_energy: -1.134147666677095\n",
            "BKT transformed Hamiltonian:\n",
            "(-0.16733398905695201+0j) [] +\n",
            "(0.04615669588901533+0j) [X0 Z1 X2] +\n",
            "(0.04615669588901533+0j) [X0 Z1 X2 Z3] +\n",
            "(0.04615669588901533+0j) [Y0 Z1 Y2] +\n",
            "(0.04615669588901533+0j) [Y0 Z1 Y2 Z3] +\n",
            "(0.16251648748871642+0j) [Z0] +\n",
            "(0.16251648748871636+0j) [Z0 Z1] +\n",
            "(0.1633603430909739+0j) [Z0 Z1 Z2] +\n",
            "(0.1633603430909739+0j) [Z0 Z1 Z2 Z3] +\n",
            "(0.11720364720195856+0j) [Z0 Z2] +\n",
            "(0.11720364720195856+0j) [Z0 Z2 Z3] +\n",
            "(0.1658325372159041+0j) [Z1] +\n",
            "(-0.19744293699755838+0j) [Z1 Z2 Z3] +\n",
            "(0.17169788392286722+0j) [Z1 Z3] +\n",
            "(-0.1974429369975584+0j) [Z2]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "H0DLpARr5sIb",
        "colab_type": "text"
      },
      "source": [
        "### Exercise\n",
        "- The BCS mean-field d-wave model of superconductivity has the Hamiltonian\n",
        "$$\n",
        "H = - t \\sum_{\\langle i,j \\rangle} \\sum_\\sigma\n",
        "        (a^\\dagger_{i, \\sigma} a_{j, \\sigma} +\n",
        "         a^\\dagger_{j, \\sigma} a_{i, \\sigma})\n",
        "    - \\sum_{\\langle i,j \\rangle} \\Delta_{ij}\n",
        "      (a^\\dagger_{i, \\uparrow} a^\\dagger_{j, \\downarrow} -\n",
        "       a^\\dagger_{i, \\downarrow} a^\\dagger_{j, \\uparrow} +\n",
        "       a_{j, \\downarrow} a_{i, \\uparrow} -\n",
        "       a_{j, \\uparrow} a_{i, \\downarrow})\n",
        "$$\n",
        "Use the `mean_field_dwave` function to generate an instance of this model with dimensions 10x10.\n",
        "    - Convert the Hamiltonian to a QubitOperator with the JWT. What is the length of the longest Pauli string that appears?\n",
        "    - Convert the Hamiltonian to a QubitOperator with the BKT. What is the length of the longest Pauli string that appears?\n",
        "    - Convert the Hamiltonian to a QuadraticHamiltonian. Get its ground energy using the `ground_energy` method of QuadraticHamiltonian. What would happen if you tried to compute the ground energy by converting to a sparse matrix?"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Zrnv4DLRuFJM",
        "colab_type": "text"
      },
      "source": [
        "## Hamiltonian simulation with Trotter formulas\n",
        "\n",
        "- Goal: apply $\\exp(-i H t)$ where $H = \\sum_j H_j$\n",
        "- Use an approximation such as $\\exp(-i H t) \\approx (\\prod_{j=1} \\exp(-i H_j t/r))^r$\n",
        "- Exposed via the `simulate_trotter` function\n",
        "- Currently implemented algorithms are from [arXiv:1706.00023](https://arxiv.org/pdf/1706.00023.pdf), [arXiv:1711.04789](https://arxiv.org/pdf/1711.04789.pdf), and [arXiv:1808.02625](https://arxiv.org/pdf/1808.02625.pdf), and are based on the JWT\n",
        "- Currently supported Hamiltonian types: DiagonalCoulombHamiltonian and InteractionOperator\n",
        "\n",
        "As a demonstration, we'll simulate time evolution under the hydrogen molecule Hamiltonian we generated earlier.\n",
        "\n",
        "First, let's create a random initial state and apply the exact time evolution by matrix exponentiation:\n",
        "$$\n",
        "\\lvert \\psi \\rangle \\mapsto \\exp(-i H t) \\lvert \\psi \\rangle\n",
        "$$"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "_e5mbQI61fdT",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Create a random initial state\n",
        "n_qubits = of.count_qubits(hamiltonian)\n",
        "initial_state = of.haar_random_vector(2**n_qubits, seed=7)\n",
        "\n",
        "# Set evolution time\n",
        "time = 1.0\n",
        "\n",
        "# Apply exp(-i H t) to the state\n",
        "exact_state = scipy.sparse.linalg.expm_multiply(-1j*hamiltonian_jw_sparse*time, initial_state)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_OZPjkN513zJ",
        "colab_type": "text"
      },
      "source": [
        "Now, let's create a circuit to perform the evolution and compare the fidelity of the resulting state with the one from exact evolution. The fidelity can be increased by increasing the number of Trotter steps. Note that the Hamiltonian input to `simulate_trotter` should be an InteractionOperator, not a FermionOperator."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1DXSZ54u12Tt",
        "colab_type": "code",
        "outputId": "61bfdd7a-f30c-4a12-cc45-a6b909e2e4f0",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "import cirq\n",
        "import openfermioncirq as ofc\n",
        "import numpy as np\n",
        "\n",
        "# Initialize qubits\n",
        "qubits = cirq.LineQubit.range(n_qubits)\n",
        "\n",
        "# Create circuit\n",
        "circuit = cirq.Circuit.from_ops(\n",
        "    ofc.simulate_trotter(\n",
        "        qubits, hamiltonian, time,\n",
        "        n_steps=10,\n",
        "        order=0,\n",
        "        algorithm=ofc.trotter.LOW_RANK)\n",
        ")\n",
        "\n",
        "# Apply the circuit to the initial state\n",
        "result = circuit.apply_unitary_effect_to_state(initial_state)\n",
        "\n",
        "# Compute the fidelity with the final state from exact evolution\n",
        "fidelity = abs(np.dot(exact_state, result.conj()))**2\n",
        "\n",
        "print(fidelity)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0.9999820449924591\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "tG4PCh4faFTL",
        "colab_type": "code",
        "outputId": "146d17d0-d648-4b2a-9885-1fcb2217d36f",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 17732
        }
      },
      "source": [
        "print(circuit.to_text_diagram(transpose=True))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0           1           2           3\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.052π)  Rz(0.052π)  Rz(0.03π)   Rz(0.03π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-1       Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-1\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.022    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.011π)\n",
            "│           │           │           │\n",
            "Rz(-0.01π)  Rz(-0.01π)  Rz(-0.011π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-0.5   Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.006\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0.006\n",
            "│           │           │           │\n",
            "@───────────@^0.006     ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "Rz(-0.003π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.003π) Rz(-0.003π) Rz(-0.003π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(π)       Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-0.5     Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^0         Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0         │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.052π)\n",
            "│           │           │           │\n",
            "Rz(0.03π)   Rz(0.03π)   Rz(0.052π)  Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-1\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-1     Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.022\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "Rz(-0.011π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.011π) Rz(-0.01π)  Rz(-0.01π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^0.5      Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0.006     │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.003π)\n",
            "│           │           │           │\n",
            "Rz(-0.003π) Rz(-0.003π) Rz(-0.003π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(π)       Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^0.5    Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.052π)  Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.052π)  Rz(0.03π)   Rz(0.03π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-1       Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-1\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.022    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.011π)\n",
            "│           │           │           │\n",
            "Rz(-0.01π)  Rz(-0.01π)  Rz(-0.011π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-0.5   Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.006\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0.006\n",
            "│           │           │           │\n",
            "@───────────@^0.006     ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "Rz(-0.003π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.003π) Rz(-0.003π) Rz(-0.003π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(π)       Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-0.5     Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^0         Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0         │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.052π)\n",
            "│           │           │           │\n",
            "Rz(0.03π)   Rz(0.03π)   Rz(0.052π)  Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-1\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-1     Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.022\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "Rz(-0.011π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.011π) Rz(-0.01π)  Rz(-0.01π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^0.5      Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0.006     │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.003π)\n",
            "│           │           │           │\n",
            "Rz(-0.003π) Rz(-0.003π) Rz(-0.003π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(π)       Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^0.5    Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.052π)  Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.052π)  Rz(0.03π)   Rz(0.03π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-1       Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-1\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.022    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.011π)\n",
            "│           │           │           │\n",
            "Rz(-0.01π)  Rz(-0.01π)  Rz(-0.011π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-0.5   Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.006\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0.006\n",
            "│           │           │           │\n",
            "@───────────@^0.006     ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "Rz(-0.003π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.003π) Rz(-0.003π) Rz(-0.003π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(π)       Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-0.5     Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^0         Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0         │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.052π)\n",
            "│           │           │           │\n",
            "Rz(0.03π)   Rz(0.03π)   Rz(0.052π)  Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-1\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-1     Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.022\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "Rz(-0.011π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.011π) Rz(-0.01π)  Rz(-0.01π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^0.5      Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0.006     │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.003π)\n",
            "│           │           │           │\n",
            "Rz(-0.003π) Rz(-0.003π) Rz(-0.003π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(π)       Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^0.5    Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.052π)  Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.052π)  Rz(0.03π)   Rz(0.03π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-1       Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-1\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.022    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.011π)\n",
            "│           │           │           │\n",
            "Rz(-0.01π)  Rz(-0.01π)  Rz(-0.011π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-0.5   Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.006\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0.006\n",
            "│           │           │           │\n",
            "@───────────@^0.006     ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "Rz(-0.003π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.003π) Rz(-0.003π) Rz(-0.003π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(π)       Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-0.5     Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^0         Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0         │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.052π)\n",
            "│           │           │           │\n",
            "Rz(0.03π)   Rz(0.03π)   Rz(0.052π)  Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-1\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-1     Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.022\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "Rz(-0.011π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.011π) Rz(-0.01π)  Rz(-0.01π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^0.5      Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0.006     │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.003π)\n",
            "│           │           │           │\n",
            "Rz(-0.003π) Rz(-0.003π) Rz(-0.003π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(π)       Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^0.5    Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.052π)  Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.052π)  Rz(0.03π)   Rz(0.03π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-1       Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-1\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.022    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.011π)\n",
            "│           │           │           │\n",
            "Rz(-0.01π)  Rz(-0.01π)  Rz(-0.011π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-0.5   Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.006\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0.006\n",
            "│           │           │           │\n",
            "@───────────@^0.006     ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "Rz(-0.003π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.003π) Rz(-0.003π) Rz(-0.003π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(π)       Rz(0.0π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^-0.5     Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^0         Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0         │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    Rz(-0.0π)\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)   Rz(0.052π)\n",
            "│           │           │           │\n",
            "Rz(0.03π)   Rz(0.03π)   Rz(0.052π)  Rz(0.0π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(0.0π)    Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-1\n",
            "│           │           │           │\n",
            "#2──────────YXXY^-1     Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^-0.022\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^-0.021\n",
            "│           │           │           │\n",
            "@───────────@^-0.021    ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^-0.021    │\n",
            "│           │           │           │\n",
            "Rz(-0.011π) ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(π)       Rz(-0.011π) Rz(-0.01π)  Rz(-0.01π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(π)\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       │\n",
            "│           │           │           │\n",
            "YXXY────────#2^0.5      Z^0         │\n",
            "│           │           │           │\n",
            "│           Z^0         YXXY────────#2^-0.5\n",
            "│           │           │           │\n",
            "│           YXXY────────#2^-1       Z^0\n",
            "│           │           │           │\n",
            "@───────────@^-0.006    Z^0         │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^-0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "@───────────@^0.006     │           │\n",
            "│           │           │           │\n",
            "×───────────×           @───────────@^0.006\n",
            "│           │           │           │\n",
            "│           │           ×───────────×\n",
            "│           │           │           │\n",
            "│           @───────────@^0.006     │\n",
            "│           │           │           │\n",
            "│           ×───────────×           Rz(-0.003π)\n",
            "│           │           │           │\n",
            "Rz(-0.003π) Rz(-0.003π) Rz(-0.003π) Rz(π)\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(π)       Rz(0.0π)    │\n",
            "│           │           │           │\n",
            "│           #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         #2──────────YXXY^-0.5\n",
            "│           │           │           │\n",
            "#2──────────YXXY^0.5    Z^0         │\n",
            "│           │           │           │\n",
            "Z^0         #2──────────YXXY^-1     │\n",
            "│           │           │           │\n",
            "│           Z^0         @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "│           ×───────────×           │\n",
            "│           │           │           │\n",
            "│           │           @───────────@^0\n",
            "│           │           │           │\n",
            "@───────────@^0         ×───────────×\n",
            "│           │           │           │\n",
            "×───────────×           │           │\n",
            "│           │           │           │\n",
            "│           @───────────@^0         │\n",
            "│           │           │           │\n",
            "Rz(-0.0π)   ×───────────×           │\n",
            "│           │           │           │\n",
            "Rz(0.0π)    Rz(-0.0π)   Rz(-0.0π)   Rz(-0.0π)\n",
            "│           │           │           │\n",
            "│           Rz(0.0π)    Rz(0.0π)    Rz(0.0π)\n",
            "│           │           │           │\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "s_d1TcaWekK_",
        "colab_type": "text"
      },
      "source": [
        "## Variational energy calculation"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1uOh_pQfgX4O",
        "colab_type": "text"
      },
      "source": [
        "- Approximate the ground energy by minimizing the cost function\n",
        "$$\n",
        "E(\\vec \\theta) =  \\langle \\psi \\rvert\n",
        "U^\\dagger(\\vec{\\theta}) H U(\\vec{\\theta})\n",
        "\\lvert \\psi\\rangle.\n",
        "$$\n",
        "- The parameterized circuit $U(\\vec{\\theta})$ is called an ansatz\n",
        "- A popular choice is to use an ansatz of the form\n",
        "$$\n",
        "U(\\vec{\\theta}) = \\prod_j \\exp(-i \\theta_j H_j)\n",
        "$$\n",
        "where $H = \\sum_j H_j$\n",
        "- OpenFermion-Cirq contains some built-in ansatzes of this form based on Trotter steps used in Hamiltonian simulation."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "VbV7nJkhfG4S",
        "colab_type": "code",
        "outputId": "26375d9a-aeb4-44aa-9453-a93ab302b01e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1577
        }
      },
      "source": [
        "import cirq\n",
        "import openfermioncirq as ofc\n",
        "\n",
        "ansatz = ofc.LowRankTrotterAnsatz(hamiltonian)\n",
        "\n",
        "cirq.DropNegligible().optimize_circuit(ansatz.circuit)\n",
        "print(ansatz.circuit.to_text_diagram(transpose=True))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0         1           2           3\n",
            "│         │           │           │\n",
            "Z^U_0_0   Z^U_1_0     Z^U_2_0     Z^U_3_0\n",
            "│         │           │           │\n",
            "│         YXXY────────#2^-1       │\n",
            "│         │           │           │\n",
            "YXXY──────#2^-1       │           │\n",
            "│         │           │           │\n",
            "│         │           YXXY────────#2^-1\n",
            "│         │           │           │\n",
            "│         YXXY────────#2^-1       │\n",
            "│         │           │           │\n",
            "@─────────@^V_0_1_0_0 │           │\n",
            "│         │           │           │\n",
            "×─────────×           @───────────@^V_2_3_0_0\n",
            "│         │           │           │\n",
            "│         │           ×───────────×\n",
            "│         │           │           │\n",
            "│         @───────────@^V_0_3_0_0 │\n",
            "│         │           │           │\n",
            "│         ×───────────×           │\n",
            "│         │           │           │\n",
            "@─────────@^V_1_3_0_0 @───────────@^V_0_2_0_0\n",
            "│         │           │           │\n",
            "×─────────×           ×───────────×\n",
            "│         │           │           │\n",
            "Z^U_3_0_0 @───────────@^V_1_2_0_0 Z^U_0_0_0\n",
            "│         │           │           │\n",
            "Rz(π)     ×───────────×           Rz(π)\n",
            "│         │           │           │\n",
            "│         Z^U_2_0_0   Z^U_1_0_0   │\n",
            "│         │           │           │\n",
            "│         #2──────────YXXY^-1     │\n",
            "│         │           │           │\n",
            "│         │           #2──────────YXXY^0.5\n",
            "│         │           │           │\n",
            "#2────────YXXY^-0.5   │           │\n",
            "│         │           │           │\n",
            "│         #2──────────YXXY^-1     │\n",
            "│         │           │           │\n",
            "│         │           @───────────@^V_0_1_1_0\n",
            "│         │           │           │\n",
            "@─────────@^V_2_3_1_0 ×───────────×\n",
            "│         │           │           │\n",
            "×─────────×           │           │\n",
            "│         │           │           │\n",
            "│         @───────────@^V_0_3_1_0 │\n",
            "│         │           │           │\n",
            "│         ×───────────×           │\n",
            "│         │           │           │\n",
            "@─────────@^V_0_2_1_0 @───────────@^V_1_3_1_0\n",
            "│         │           │           │\n",
            "×─────────×           ×───────────×\n",
            "│         │           │           │\n",
            "Z^U_0_1_0 @───────────@^V_1_2_1_0 Z^U_3_1_0\n",
            "│         │           │           │\n",
            "Rz(π)     ×───────────×           │\n",
            "│         │           │           │\n",
            "│         Z^U_1_1_0   Z^U_2_1_0   │\n",
            "│         │           │           │\n",
            "│         │           Rz(π)       │\n",
            "│         │           │           │\n",
            "│         YXXY────────#2^-1       │\n",
            "│         │           │           │\n",
            "YXXY──────#2^-0.5     │           │\n",
            "│         │           │           │\n",
            "│         │           YXXY────────#2^0.5\n",
            "│         │           │           │\n",
            "│         YXXY────────#2^-1       │\n",
            "│         │           │           │\n",
            "@─────────@^V_0_1_2_0 │           │\n",
            "│         │           │           │\n",
            "×─────────×           @───────────@^V_2_3_2_0\n",
            "│         │           │           │\n",
            "│         │           ×───────────×\n",
            "│         │           │           │\n",
            "│         @───────────@^V_0_3_2_0 │\n",
            "│         │           │           │\n",
            "│         ×───────────×           │\n",
            "│         │           │           │\n",
            "@─────────@^V_1_3_2_0 @───────────@^V_0_2_2_0\n",
            "│         │           │           │\n",
            "×─────────×           ×───────────×\n",
            "│         │           │           │\n",
            "Z^U_3_2_0 @───────────@^V_1_2_2_0 Z^U_0_2_0\n",
            "│         │           │           │\n",
            "│         ×───────────×           │\n",
            "│         │           │           │\n",
            "│         Z^U_2_2_0   Z^U_1_2_0   │\n",
            "│         │           │           │\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OPBaF1rEWcm8",
        "colab_type": "code",
        "outputId": "2336a705-bbab-40b3-9c61-3b713aae5121",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 52
        }
      },
      "source": [
        "import scipy.optimize\n",
        "\n",
        "def energy_from_params(x):\n",
        "  param_resolver = ansatz.param_resolver(x)\n",
        "  circuit = cirq.resolve_parameters(ansatz.circuit, param_resolver)\n",
        "  final_state = circuit.apply_unitary_effect_to_state(0b1100)\n",
        "  return of.expectation(hamiltonian_jw_sparse, final_state).real\n",
        "\n",
        "initial_guess = ansatz.default_initial_params()\n",
        "result = scipy.optimize.minimize(energy_from_params, initial_guess)\n",
        "\n",
        "print('Initial energy: {}'.format(energy_from_params(initial_guess)))\n",
        "print('Optimized energy: {}'.format(result.fun))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Initial energy: -0.1660660012408567\n",
            "Optimized energy: -1.1341476666770485\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vim-c2VhuGZO",
        "colab_type": "text"
      },
      "source": [
        "## Bogoliubov transformation\n",
        "\n",
        "- Single-particle orbital basis change\n",
        "- In the particle-conserving case, takes the form\n",
        "$$\n",
        "U a_p^\\dagger U^\\dagger = b_p^\\dagger, \\quad b_p^\\dagger = \\sum_{q} u_{pq} a_q^\\dagger\n",
        "$$\n",
        "and $u$ is unitary.\n",
        "- Can be used to diagonalize any quadratic Hamiltonian:\n",
        "$$\n",
        "\\sum_{p, q} T_{pq} a_p^\\dagger a_q \\mapsto \\sum_{j} \\varepsilon_j b_j^\\dagger b_j + \\text{constant}\n",
        "$$\n",
        "- Implementation from [arXiv:1711.05395](https://arxiv.org/pdf/1711.05395.pdf); uses linear depth and linear connectivity\n",
        "\n",
        "As an example, we'll prepare the ground state of a random particle-conserving quadratic Hamiltonian"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "sOhY4QQtuGZP",
        "colab_type": "code",
        "outputId": "cb9e6cdb-df22-4b88-8ba7-e2bd0c580fee",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 468
        }
      },
      "source": [
        "n_qubits = 5\n",
        "quad_ham = of.random_quadratic_hamiltonian(\n",
        "    n_qubits, conserves_particle_number=True, seed=7)\n",
        "\n",
        "print(of.get_fermion_operator(quad_ham))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1.690525703800356 [] +\n",
            "(0.5315776978980016+0j) [0^ 0] +\n",
            "(-1.347208023348913+2.7004721387490935j) [0^ 1] +\n",
            "(-0.28362365442898696-1.8784499457335426j) [0^ 2] +\n",
            "(0.12594647819298657-1.3106154125325498j) [0^ 3] +\n",
            "(-0.3880303291443195-1.1751249212322041j) [0^ 4] +\n",
            "(-1.347208023348913-2.7004721387490935j) [1^ 0] +\n",
            "(2.5012533818678193+0j) [1^ 1] +\n",
            "(0.3391421007279024-3.8305756810505094j) [1^ 2] +\n",
            "(-0.3509690502067961+0.090677856754656j) [1^ 3] +\n",
            "(1.8575239595653907-1.4736314761076197j) [1^ 4] +\n",
            "(-0.28362365442898696+1.8784499457335426j) [2^ 0] +\n",
            "(0.3391421007279024+3.8305756810505094j) [2^ 1] +\n",
            "(-0.019560786804260433+0j) [2^ 2] +\n",
            "(-2.979765944360631+2.5490724453105917j) [2^ 3] +\n",
            "(0.5091942820312417+0.344618218148502j) [2^ 4] +\n",
            "(0.12594647819298657+1.3106154125325498j) [3^ 0] +\n",
            "(-0.3509690502067961-0.090677856754656j) [3^ 1] +\n",
            "(-2.979765944360631-2.5490724453105917j) [3^ 2] +\n",
            "(3.767336752913784+0j) [3^ 3] +\n",
            "(-1.2963431636902167-1.5288970105744286j) [3^ 4] +\n",
            "(-0.3880303291443195+1.1751249212322041j) [4^ 0] +\n",
            "(1.8575239595653907+1.4736314761076197j) [4^ 1] +\n",
            "(0.5091942820312417-0.344618218148502j) [4^ 2] +\n",
            "(-1.2963431636902167+1.5288970105744286j) [4^ 3] +\n",
            "(-0.3445183403145406+0j) [4^ 4]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HwObrpO5uGZS",
        "colab_type": "text"
      },
      "source": [
        "Now we construct a circuit which maps computational basis states to eigenstates of the Hamiltonian."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "P1w7kKokuGZT",
        "colab_type": "code",
        "outputId": "fbcab7b5-7fd7-49f6-c979-ebc2295c4737",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 503
        }
      },
      "source": [
        "_, basis_change_matrix, _ = quad_ham.diagonalizing_bogoliubov_transform()\n",
        "\n",
        "qubits = cirq.LineQubit.range(n_qubits)\n",
        "circuit = cirq.Circuit.from_ops(\n",
        "    ofc.bogoliubov_transform(\n",
        "        qubits,\n",
        "        basis_change_matrix))\n",
        "\n",
        "print(circuit.to_text_diagram(transpose=True))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0         1        2         3          4\n",
            "│         │        │         │          │\n",
            "Rz(-0.0π) Rz(0.0π) Rz(π)     Rz(-π)     Rz(-0.0π)\n",
            "│         │        │         │          │\n",
            "│         │        │         YXXY───────#2^0.073\n",
            "│         │        │         │          │\n",
            "│         │        YXXY──────#2^(5/11)  Z^(-7/9)\n",
            "│         │        │         │          │\n",
            "│         YXXY─────#2^0.814  Z^-0.508   │\n",
            "│         │        │         │          │\n",
            "│         │        Z^-0.304  YXXY───────#2^0.381\n",
            "│         │        │         │          │\n",
            "YXXY──────#2^0.703 │         │          Z^0.401\n",
            "│         │        │         │          │\n",
            "│         Z^-0.767 YXXY──────#2^(13/16) │\n",
            "│         │        │         │          │\n",
            "│         YXXY─────#2^(7/11) Z^(-13/14) │\n",
            "│         │        │         │          │\n",
            "│         │        Z^0.393   YXXY───────#2^0.481\n",
            "│         │        │         │          │\n",
            "│         │        YXXY──────#2^0.422   Z^-0.738\n",
            "│         │        │         │          │\n",
            "│         │        │         Z^-0.824   │\n",
            "│         │        │         │          │\n",
            "│         │        │         YXXY───────#2^0.506\n",
            "│         │        │         │          │\n",
            "│         │        │         │          Z^(5/7)\n",
            "│         │        │         │          │\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-jDHy5izuGZV",
        "colab_type": "text"
      },
      "source": [
        "In the rotated basis, the quadratic Hamiltonian takes the form\n",
        "$$\n",
        "H = \\sum_j \\varepsilon_j b_j^\\dagger b_j + \\text{constant}\n",
        "$$\n",
        "We can get the $\\varepsilon_j$ and the constant using the `orbital_energies` method of QuadraticHamiltonian."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Q0aZhjc0uGZW",
        "colab_type": "code",
        "outputId": "b6d7d0e0-5ff9-4076-9bbf-60ae4f31edd9",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 52
        }
      },
      "source": [
        "orbital_energies, constant = quad_ham.orbital_energies()\n",
        "\n",
        "print(orbital_energies)\n",
        "print(constant)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[-6.25377614 -1.2291963   0.71202361  5.0062515   8.20078604]\n",
            "1.690525703800356\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "YCsxdHRpuGZZ",
        "colab_type": "text"
      },
      "source": [
        "The ground state of the Hamiltonian is prepared by filling in the orbitals with negative energy."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ggOZq0DXuGZZ",
        "colab_type": "code",
        "outputId": "1d156938-996d-4bef-8f0b-e3c6e645fa14",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 52
        }
      },
      "source": [
        "# Apply the circuit with initial state having the first two modes occupied.\n",
        "result = circuit.apply_unitary_effect_to_state(0b11000)\n",
        "\n",
        "# Compute the expectation value of the final state with the Hamiltonian\n",
        "quad_ham_sparse = of.get_sparse_operator(quad_ham)\n",
        "print(of.expectation(quad_ham_sparse, result))\n",
        "\n",
        "# Print out the ground state energy; it should match\n",
        "print(quad_ham.ground_energy())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "(-5.7924467380600495+5.551115123125783e-17j)\n",
            "-5.792446738060049\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6WXdbSBmuGZc",
        "colab_type": "text"
      },
      "source": [
        "Recall that the Jordan-Wigner transform of $b_j^\\dagger b_j$ is $\\frac12(I-Z)$. Therefore, $\\exp(-i \\varepsilon_j b_j^\\dagger b_j)$ is equivalent to a single-qubit Z rotation under the JWT. Since the operators $b_j^\\dagger b_j$ commute, we have\n",
        "$$\n",
        "\\exp(-i H t) = \\exp(-i \\sum_j \\varepsilon_j b_j^\\dagger b_j t)\n",
        "= \\prod_j \\exp(-i \\varepsilon_j b_j^\\dagger b_j t)\n",
        "$$\n",
        "This gives a method for simulating time evolution under a quadratic Hamiltonian:\n",
        "- Use a Bogoliubov transformation to change to the basis in which the Hamiltonian is diagonal (Note: this transformation might be the inverse of what you expect. In that case, use `cirq.inverse`)\n",
        "- Apply single-qubit Z-rotations with angles proportional to the orbital energies\n",
        "- Undo the basis change\n",
        "\n",
        "The code cell below creates a random initial state and applies time evolution by direct matrix exponentiation."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "pqELuMY8uGZd",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from scipy.sparse.linalg import expm_multiply\n",
        "\n",
        "# Create a random initial state\n",
        "initial_state = of.haar_random_vector(2**n_qubits)\n",
        "\n",
        "# Set evolution time\n",
        "time = 1.0\n",
        "\n",
        "# Apply exp(-i H t) to the state\n",
        "final_state = expm_multiply(-1j*quad_ham_sparse*time, initial_state)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dFzXiKp0uGZf",
        "colab_type": "text"
      },
      "source": [
        "### Exercise\n",
        "\n",
        "Fill in the code cell below to construct a circuit which applies $\\exp(-i H t)$ using the method described above"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "f0y43UhbuGZh",
        "colab_type": "code",
        "outputId": "a2702243-cb0a-4c45-d06a-215dff5f5f7b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "# Initialize qubits\n",
        "qubits = cirq.LineQubit.range(n_qubits)\n",
        "\n",
        "# Write code below to create the circuit\n",
        "# You should define the `circuit` variable here\n",
        "# ---------------------------------------------\n",
        "\n",
        "\n",
        "# ---------------------------------------------\n",
        "\n",
        "# Apply the circuit to the initial state\n",
        "result = circuit.apply_unitary_effect_to_state(initial_state)\n",
        "\n",
        "# Compute the fidelity with the correct final state\n",
        "fidelity = abs(np.dot(final_state, result.conj()))**2\n",
        "\n",
        "# Print fidelity; it should be 1\n",
        "print(fidelity)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0.04707626296466583\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Wp1a_Zf8EUen",
        "colab_type": "text"
      },
      "source": [
        "### Solution"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "QHQvLlf1uGZt",
        "colab_type": "code",
        "outputId": "9f895d18-385a-4d77-c1b8-c35f0d20afd9",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "# Initialize qubits\n",
        "qubits = cirq.LineQubit.range(n_qubits)\n",
        "\n",
        "# Write code below to create the circuit\n",
        "# You should define the `circuit` variable here\n",
        "# ---------------------------------------------\n",
        "def exponentiate_quad_ham(qubits, quad_ham):\n",
        "    _, basis_change_matrix, _ = quad_ham.diagonalizing_bogoliubov_transform()\n",
        "    orbital_energies, _ = quad_ham.orbital_energies()\n",
        "    \n",
        "    yield cirq.inverse(\n",
        "        ofc.bogoliubov_transform(qubits, basis_change_matrix))\n",
        "    for i in range(len(qubits)):\n",
        "        yield cirq.Rz(rads=-orbital_energies[i]).on(qubits[i])\n",
        "    yield ofc.bogoliubov_transform(qubits, basis_change_matrix)\n",
        "\n",
        "circuit = cirq.Circuit.from_ops(exponentiate_quad_ham(qubits, quad_ham))\n",
        "# ---------------------------------------------\n",
        "\n",
        "# Apply the circuit to the initial state\n",
        "result = circuit.apply_unitary_effect_to_state(initial_state)\n",
        "\n",
        "# Compute the fidelity with the correct final state\n",
        "fidelity = abs(np.dot(final_state, result.conj()))**2\n",
        "\n",
        "# Print fidelity; it should be 1\n",
        "print(fidelity)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0.9999999999999991\n"
          ],
          "name": "stdout"
        }
      ]
    }
  ]
}